#include <stdlib.h>
#include <stdio.h>
#include "../plugins.h"
#include "../xml.h"
#include "../journal.h"
#include "../tabs.h"
#include "../gui_al.h"
#include "../gui_io.h"
#include <gtk/gtk.h>

struct _tbr_file {
	char *item;
	struct _tbr_file *next;
};

struct _tbr_file *_tbr_forward = NULL;
struct _tbr_file *_tbr_back = NULL;
struct _tbr_file *_tbr_current = NULL;	//one item only!

/**Dataset to switch out _tbr_forward, _tbr_back, etc on journ changes**/
struct _tbr_state {
	char *name;
	struct _tbr_file *forward;
	struct _tbr_file *back;
	struct _tbr_file *current;
};
struct _tbr_state **_tbr_journals;
//Limited to 64 journals
//The UI won't even allow for 32 reasonably anyway...

int _tbr_new_file = 0;


GtkWidget *_bar;
int _tbr_lock = 0;


/**Pointers to button widgets**/
GtkWidget *btn_tbr_back;
GtkWidget *btn_tbr_forward;
GtkWidget *btn_cut;
GtkWidget *btn_copy;
GtkWidget *btn_paste;
GtkWidget *btn_trash;
GtkWidget *btn_tbr_back;
GtkWidget *btn_undo;
GtkWidget *btn_redo;

/***Useful gtk functions***/
void setSensitivity(GtkWidget * widget, int state)
{				//state = 0, insensitive; state=1, sensitive
	if (state)
		gtk_widget_set_sensitive(widget, TRUE);
	else
		gtk_widget_set_sensitive(widget, FALSE);
}

/*******************************/



/*Callbacks:*/
//Toolbar callbacks:
void back(GtkToolButton * toolbutton, gpointer user_data)
{
	if (_tbr_back) {
		if (elog_gui_io_save() > 1)
			return;
		_tbr_lock = 1;	//locking out the callbacks for this plgn.

		if (elog_gui_io_open(_tbr_back->item, NULL)) {
			_tbr_current->next = _tbr_forward;
			_tbr_forward = _tbr_current;
			_tbr_current = _tbr_back;
			_tbr_back = _tbr_back->next;
		}
		_tbr_lock = 0;
		if (_tbr_back)
			setSensitivity(btn_tbr_back, 1);
		if (_tbr_forward)
			setSensitivity(btn_tbr_forward, 1);
	}
	if (!_tbr_back)
		setSensitivity((GtkWidget *) toolbutton, 0);
}

void forward(GtkToolButton * toolbutton, gpointer user_data)
{
	if (_tbr_forward) {
		if (elog_gui_io_save() > 1)
			return;	//it failed to save, don't change files.
		_tbr_lock = 1;
		if (elog_gui_io_open(_tbr_forward->item, NULL)) {
			_tbr_current->next = _tbr_back;
			_tbr_back = _tbr_current;
			_tbr_current = _tbr_forward;
			_tbr_forward = _tbr_forward->next;
		}
		_tbr_lock = 0;
		if (_tbr_back)
			setSensitivity(btn_tbr_back, 1);
		if (_tbr_forward)
			setSensitivity(btn_tbr_forward, 1);
	}
	if (!_tbr_forward)
		setSensitivity((GtkWidget *) toolbutton, 0);
}

void __tbr_cut(GtkToolButton * toolbutton, gpointer user_data)
{
	elog_tab_act_cut();
}

void __tbr_copy(GtkToolButton * toolbutton, gpointer user_data)
{
	elog_tab_act_copy();
}

void __tbr_paste(GtkToolButton * toolbutton, gpointer user_data)
{
	elog_tab_act_paste();
}

void __tbr_undo(GtkToolButton * toolbutton, gpointer user_data)
{
	elog_tab_act_undo();
}

void __tbr_redo(GtkToolButton * toolbutton, gpointer user_data)
{
	elog_tab_act_redo();
}

void __tbr_trash(GtkToolButton * toolbutton, gpointer user_data)
{
	elog_tab_act_delete();
}



/* open(doc) is called each time a file is opened for the gui; not necessarily each
 * time it is opened period (that'd be quite silly and impossible).
 * doc is the same data as the program uses, it is the raw char of the file.
 * It can be accessed with elog_xml_scanf
 */
void ___open(struct elog_plgn_data_io *doc)
{
	_tbr_new_file = 0;
	if (!_tbr_lock) {
		if (_tbr_current) {
			if (doc) {
				if (strcmp(_tbr_current->item, doc->fileName)
			    	!= 0) {
					_tbr_current->next = _tbr_back;
					_tbr_back = _tbr_current;
					_tbr_current =
					    malloc(sizeof *_tbr_current);
					elog_sp_cat(&(_tbr_current->item),
						    doc->fileName, NULL);
					_tbr_current->next = NULL;
				}
			}
			else {
				_tbr_new_file = 1;
			}
			//else, it's the same file reopened.
		} 
		else {
			if (doc) {
				_tbr_current = malloc(sizeof *_tbr_current);
				elog_sp_cat(&(_tbr_current->item),
					    doc->fileName, NULL);
				_tbr_current->next = NULL;
			}
			else {
				_tbr_new_file = 1;
			}
		}
		if (_tbr_back)
			setSensitivity(btn_tbr_back, 1);
		if (_tbr_forward)
			setSensitivity(btn_tbr_forward, 1);
	}
}
/* save(doc) is called each time a file is saved.
 *	
 */
void ___save(struct elog_plgn_data_io *doc)
{
	if (_tbr_new_file) {
		___open(doc);
		_tbr_new_file = 0;
	}
}
/* init(gui) is called when the plugin is loaded.
 * gui will be NULL;
 */
void ___init(void *ignoreme)	//add in the gui struct once you've made it.
{
	_bar = gtk_toolbar_new();
	gtk_box_pack_start(GTK_BOX(_mainBox), _bar, FALSE, FALSE, 0);
	gtk_box_reorder_child(GTK_BOX(_mainBox), _bar, 1);


	GtkToolItem *item =
	    gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 0);


	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(back), NULL);
	btn_tbr_back = (GtkWidget *) item;

	item = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 1);


	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(forward), NULL);
	btn_tbr_forward = (GtkWidget *) item;


	item = gtk_separator_tool_item_new();
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 2);


	item = gtk_tool_button_new_from_stock(GTK_STOCK_CUT);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 3);

	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(__tbr_cut), NULL);
	btn_cut = (GtkWidget *) item;

	item = gtk_tool_button_new_from_stock(GTK_STOCK_COPY);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 4);

	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(__tbr_copy), NULL);
	btn_copy = (GtkWidget *) item;

	item = gtk_tool_button_new_from_stock(GTK_STOCK_PASTE);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 5);

	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(__tbr_paste), NULL);
	btn_paste = (GtkWidget *) item;

	item = gtk_separator_tool_item_new();
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 6);


	item = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 7);

	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(__tbr_undo), NULL);
	btn_undo = (GtkWidget *) item;


	item = gtk_tool_button_new_from_stock(GTK_STOCK_REDO);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 8);

	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(__tbr_redo), NULL);
	btn_redo = (GtkWidget *) item;


	item = gtk_separator_tool_item_new();
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 9);

	item = gtk_tool_button_new_from_stock(GTK_STOCK_DELETE);
	gtk_toolbar_insert(GTK_TOOLBAR(_bar), GTK_TOOL_ITEM(item), 10);

	g_signal_connect((gpointer) item, "clicked",
			 G_CALLBACK(__tbr_trash), NULL);

	btn_trash = (GtkWidget *) item;

	setSensitivity(btn_tbr_back, 0);
	setSensitivity(btn_tbr_forward, 0);
	setSensitivity(btn_redo, 0);
	setSensitivity(btn_undo, 0);

	gtk_widget_show_all(_bar);
}

/* end(void) is called when the program unloads your plugin.  Please clean
 * everything it's done up:  Including what it's added to the gui!
 * HINT:  You should have stored the gtk widgets you needed to delete them
 * later.
 */
void ___end(void *ignoreme)
{
	gtk_widget_destroy(_bar);
}


/* char *info returns user-level information about what the plugin does.
 */
char *___info()
{
	return
	    "Toolbar -- Creates a toolbar with buttons like back/forward.";
}

/* char *author returns the list of authors, please insert a \n after
 * each author for display purposes.
 */
char *___author()
{
	return "Toolbar by Chris <MA_D> Hilton";
}

/*
 * tab is the tab being switched to.
 * this callback was added for this plugin!
 */
void ___tab(int *tab)
{

	setSensitivity(btn_undo,
		       elog_tab_capable(ELOG_TAB_ACT_UNDO, *tab));
	setSensitivity(btn_redo,
		       elog_tab_capable(ELOG_TAB_ACT_REDO, *tab));
	setSensitivity(btn_trash,
		       elog_tab_capable(ELOG_TAB_ACT_DELETE, *tab));
	setSensitivity(btn_cut, elog_tab_capable(ELOG_TAB_ACT_CUT, *tab));
	setSensitivity(btn_copy,
		       elog_tab_capable(ELOG_TAB_ACT_COPY, *tab));
	setSensitivity(btn_paste,
		       elog_tab_capable(ELOG_TAB_ACT_PASTE, *tab));
}

/*
 * This function is so that other plugins can register their 
 * needs...  It's not functional yet....
 * Note, this is not a ejourn callback, if you put it
 * in any other plugin it will just waste space.
 */
void regTab(int *tab)
{

}
